/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.store.client.components;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.elf.gwt.common.client.access.RequestParameter;
import com.elf.gwt.common.client.components.CommonSimpleComponent;
import com.elf.gwt.common.client.model.AccountModel;
import com.elf.gwt.common.client.model.AttributeValueModel;
import com.elf.gwt.common.client.model.DownloadModel;
import com.elf.gwt.common.client.model.OrderMetaModel;
import com.elf.gwt.common.client.model.OrderModel;
import com.elf.gwt.common.client.model.OrderProductModel;
import com.elf.gwt.common.client.model.OrderStatusHistoryModel;
import com.elf.gwt.common.client.model.OrderTotalModel;
import com.elf.gwt.store.client.GWTCommerceConstants;
import com.elf.gwt.store.client.StoreComponentController;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

/**
 *  
 */
public class OrderComponent extends JSONServerComponent
{	
	protected OrderMetaModel orderMetaModel;
	protected VerticalPanel bodyPanel;
	protected OrdersSummaryComponent ordersSummaryComponent;

	/**
	 * Constructor
	 */
	public OrderComponent(StoreComponentController controller, String stylePrefix)
	{
		super(controller, stylePrefix, null, false);
		if (ordersSummaryComponent == null) ordersSummaryComponent = (OrdersSummaryComponent)controller.getComponent("OrdersSummaryComponent");
		panel.setWidth("100%");
		bodyPanel = new VerticalPanel();
		bodyPanel.setWidth("100%");
		bodyPanel.addStyleName(getHandle() + "BodyPanel");
		this.setLoginRequired(true);
	}

	public boolean updateFromHistoryParameters(String[] params)
	{
		if (!super.updateFromHistoryParameters(params)) return false;
				
		int id = 0;
		if (params.length > 1) id = Integer.parseInt(params[1]);
		ordersSummaryComponent.getOrderModel().setId(id);
		storeController.getMultipleResultsComponent().addComponent(this);

		//Don't look for new products
		CommonSimpleComponent alwaysAskComponent = controller.getComponent("NewProductsComponent", false);
		if (alwaysAskComponent != null) storeController.getMultipleResultsComponent().removeComponent(alwaysAskComponent);
		
		return true;
	}

	public void additionalRequestParameters()
	{
		OrderModel model = ordersSummaryComponent.getOrderModel();
		addRequestParameter(new RequestParameter("orderId", model.getId()));
	}

	protected void buildMetaModel(JSONObject jsonObject) throws Exception
	{
		orderMetaModel = new OrderMetaModel(jsonObject);
	}

	protected void buildModel(JSONObject jsonObject) throws Exception
	{
		ordersSummaryComponent.getOrderModel().update(jsonObject);
	}

	public void buildFromModel() throws Exception
	{
		NumberFormat fmt = NumberFormat.getCurrencyFormat(StoreComponentController.currenciesComponent.getCurrencyModel().getCode());
		GWTCommerceConstants constants = storeController.getStoreConstants();

		OrderModel omodel = ordersSummaryComponent.getOrderModel();
		AccountModel amodel = StoreComponentController.accountComponent.getAccountModel();
		
		if (amodel.getId() < 1 && omodel.getId() > 0)
		{
			onSelection("");
		}
		else if (amodel.getId() < 1 && omodel.getId() > 0)
		{
			onBuilt();
		}
		else if (omodel.getId() < 0)
		{
			bodyPanel.clear();
			InlineLabel errorLabel = new InlineLabel(constants.OrderComponentError());
			bodyPanel.add(errorLabel);
			bodyPanel.setCellWidth(errorLabel, "100%");

			panel.setWidget(1, 0, bodyPanel);
			onBuilt();
		}
		else
		{
			bodyPanel.clear();
			InlineLabel orderLabel = new InlineLabel(constants.OrderComponentOrderNumberLabel() + omodel.getId() + "(" + omodel.getStatus() + ")");
			orderLabel.setStyleName(getHandle() + "Strong");
			bodyPanel.add(orderLabel);

			HorizontalPanel details1 = new HorizontalPanel();
			details1.setWidth("100%");
			try {
			details1.add(new InlineLabel(constants.OrderComponentOrderDateLabel() + " " + DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM).format(omodel.getDatePurchased())));
			} catch (Exception e){};
			
			double currencyValue = StoreComponentController.currenciesComponent.getCurrencyModel().getValue();
			double orderTotal = omodel.getTotal() * currencyValue;
			InlineLabel orderTotalLabel = new InlineLabel(constants.OrderComponentOrderTotalLabel() + " " + fmt.format(orderTotal));
			details1.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
			details1.add(orderTotalLabel);
			bodyPanel.add(details1);
			bodyPanel.add(new InlineHTML("&nbsp;"));

			HorizontalPanel details2 = new HorizontalPanel();
			details2.setWidth("100%");
			VerticalPanel details2_1 = new VerticalPanel();
			details2_1.setWidth("100%");
			InlineLabel deliveryLabel = new InlineLabel(constants.OrderComponentDeliveryAddress());
			deliveryLabel.setStyleName(getHandle() + "Strong");
			details2_1.add(deliveryLabel);
			deliveryLabel.setWordWrap(false);

			List<String> address = new ArrayList<String>();
			if (orderMetaModel.isDisplayCompany()) address.add(omodel.getShipToCompany());
			address.add(omodel.getShipToName());
			address.add(omodel.getShipToStreet());
			if (orderMetaModel.isDisplaySuburb()) address.add(omodel.getShipToSuburb());
			if (orderMetaModel.isDisplayState())
				address.add(omodel.getShipToCity() + ", " + omodel.getShipToState() + " " + omodel.getShipToPostcode());
			else
				address.add(omodel.getShipToCity() + ", " + omodel.getShipToPostcode());
			address.add(omodel.getShipToCountry());

			for (Iterator<String> iter = address.iterator(); iter.hasNext(); )
			{
				InlineLabel addressLabel = new InlineLabel(iter.next());
				addressLabel.setWordWrap(false);
				details2_1.add(addressLabel);
			}

			details2.add(details2_1);
			details2.setCellWidth(details2_1, "100%");

			List<OrderProductModel> products = omodel.getProducts();
			int numProducts = products.size();
			Grid details2_2 = new Grid(numProducts+1,3);
			InlineLabel productsLabel = new InlineLabel(constants.OrderComponentProducts());
			productsLabel.setStyleName(getHandle() + "Strong");
			details2_2.setWidget(0,1,productsLabel);
			CellFormatter cf = details2_2.getCellFormatter();
			for (int i = 0; i< numProducts; i++)
			{
				OrderProductModel product = products.get(i);
				int row = i+1;
				details2_2.setWidget(row,0,new InlineLabel("" + product.getQuantity()));
				cf.setHorizontalAlignment(row, 0, HasHorizontalAlignment.ALIGN_RIGHT);
				cf.setVerticalAlignment(row, 0, HasVerticalAlignment.ALIGN_TOP);
				String strProduct = "&nbsp;x&nbsp;" + product.getName();
				int numAttributes = product.getAttributes().size();
				for (int j = 0; j< numAttributes; j++)
				{
					AttributeValueModel attribute = product.getAttributes().get(j);
					strProduct += "<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;" + attribute.getAttributeName() + " " + attribute.getName();
				}
				int numDownloads = product.getDownloads().size();
				for (int j = 0; j< numDownloads; j++)
				{
					DownloadModel downloadModel = product.getDownloads().get(j);
					String url = "php/action_component_not_compressed.php?handle=" + getHandle() + 
					"&action=Download&downloadId=" + downloadModel.getId() + 
					"&accountId=" + StoreComponentController.accountComponent.getAccountModel().getId() + 
					"&languageId=" + StoreComponentController.languagesComponent.getLanguageModel().getId() +
					"&accountSession=" + StoreComponentController.accountComponent.getAccountModel().getSession();
					
					strProduct += "<br/><a href=\"" + url + "\" target=\"_blank\">Download " + product.getName() + "</a>";
				}
				details2_2.setWidget(row,1,new InlineHTML(strProduct));
				details2_2.setWidget(row,2,new InlineLabel(fmt.format(product.getQuantity() * currencyValue * product.getFinalPrice())));
				cf.setWordWrap(row, 0, false);
				cf.setWordWrap(row, 1, false);
				cf.setWidth(row, 0, "100%");
				cf.setHorizontalAlignment(row, 2, HasHorizontalAlignment.ALIGN_RIGHT);
			}

			details2.add(details2_2);

			bodyPanel.add(details2);
			bodyPanel.add(new InlineHTML("&nbsp;"));

			InlineLabel billingLabel = new InlineLabel(constants.OrderComponentBillingInformation());
			billingLabel.setStyleName(getHandle() + "Strong");
			bodyPanel.add(billingLabel);
			bodyPanel.add(new InlineHTML("&nbsp;"));

			HorizontalPanel details3 = new HorizontalPanel();
			details3.setWidth("100%");
			VerticalPanel details3_1 = new VerticalPanel();
			InlineLabel deliveryAddressLabel = new InlineLabel(constants.OrderComponentBillingAddress());
			deliveryAddressLabel.setWordWrap(false);
			deliveryAddressLabel.setStyleName(getHandle() + "Strong");
			details3_1.add(deliveryAddressLabel);

			address.clear();
			if (orderMetaModel.isDisplayCompany()) address.add(omodel.getBillToCompany());
			address.add(omodel.getBillToName());
			address.add(omodel.getBillToStreet());
			if (orderMetaModel.isDisplaySuburb()) address.add(omodel.getBillToSuburb());
			if (orderMetaModel.isDisplayState())
				address.add(omodel.getBillToCity() + ", " + omodel.getBillToState() + " " + omodel.getBillToPostcode());
			else
				address.add(omodel.getBillToCity() + ", " + omodel.getBillToPostcode());
			address.add(omodel.getBillToCountry());

			for (Iterator<String> iter = address.iterator(); iter.hasNext(); )
			{
				InlineLabel addressLabel = new InlineLabel(iter.next());
				addressLabel.setWordWrap(false);
				details3_1.add(addressLabel);
			}

			details3.add(details3_1);
			details3.setCellWidth(details3_1, "100%");

			List<OrderTotalModel> totals = omodel.getTotals();
			int numTotals = totals.size();
			Grid details3_2 = new Grid(numTotals,2);
			cf = details3_2.getCellFormatter();
			for (int i = 0; i< numTotals; i++)
			{
				OrderTotalModel total = totals.get(i);
				details3_2.setWidget(i,0,new InlineLabel(total.getTitle()));
				cf.setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
				InlineLabel totalLabel = new InlineLabel(fmt.format(currencyValue * total.getValue()));
				if (total.getTotalClass().equals("ot_total"))
					totalLabel.setStyleName(getHandle() + "Strong");
				details3_2.setWidget(i,1,totalLabel);
				cf.setHorizontalAlignment(i, 1, HasHorizontalAlignment.ALIGN_RIGHT);
				cf.setWidth(i,0, "100%");
				cf.setWordWrap(i, 0, false);
				cf.setWordWrap(i, 1, false);
			}
			details3.add(details3_2);

			bodyPanel.add(details3);


			bodyPanel.add(new InlineHTML("&nbsp;"));
			InlineLabel paymentLabel = new InlineLabel(constants.OrderComponentPaymentMethod());
			paymentLabel.setStyleName(getHandle() + "Strong");
			bodyPanel.add(paymentLabel);
			bodyPanel.add(new InlineLabel(omodel.getPaymentMethod()));

			bodyPanel.add(new InlineHTML("&nbsp;"));

			InlineLabel historyLabel = new InlineLabel(constants.OrderComponentOrderHistory());
			historyLabel.setStyleName(getHandle() + "Strong");
			bodyPanel.add(historyLabel);

			List<OrderStatusHistoryModel> histories = omodel.getHistories();
			int numHistories = histories.size();
			Grid details4 = new Grid(numHistories,3);
			cf = details4.getCellFormatter();
			for (int i = 0; i< numHistories; i++)
			{
				OrderStatusHistoryModel history = histories.get(i);
				details4.setText(i, 0, DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM).format(history.getDateAdded()));
				details4.setText(i, 1, history.getStatus());
				details4.setHTML(i, 2, history.getComments());
			}
			bodyPanel.add(details4);
			Button cancelButton = new Button(controller.getCommonConstants().GoBack(), 
					new ClickHandler() {
						public void onClick(ClickEvent event) {
							onSelection("OrdersSummaryComponent");
						}}
			);
			bodyPanel.add(cancelButton);
			bodyPanel.setCellHorizontalAlignment(cancelButton, HasHorizontalAlignment.ALIGN_RIGHT);
			panel.setWidget(1, 0, bodyPanel);

			onBuilt();
		}
	}
}
